/*
 * SPDX-FileCopyrightText: 2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

package com.sanji.audio_test.rule

import android.app.Application
import android.net.Uri
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.sanji.audio_test.ContactGroupInfo
import com.sanji.audio_test.ContactInfo
import com.sanji.audio_test.GroupLookup
import com.sanji.audio_test.getContactByLookupKey
import com.sanji.audio_test.getContactGroupById
import com.sanji.audio_test.withContactsByUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * 录音规则编辑器ViewModel
 * 负责管理录音规则编辑器的数据和业务逻辑
 * @param application 应用程序实例
 */
class RecordRuleEditorViewModel(application: Application) : AndroidViewModel(application) {
    // 联系人信息查找状态流
    private val _contactInfoLookup = MutableStateFlow<ContactInfo?>(null)
    val contactInfoLookup = _contactInfoLookup.asStateFlow()

    // 联系人组信息查找状态流
    private val _contactGroupInfoLookup = MutableStateFlow<ContactGroupInfo?>(null)
    val contactGroupInfoLookup = _contactGroupInfoLookup.asStateFlow()

    // 联系人信息选择状态流
    private val _contactInfoSelection = MutableStateFlow<ContactInfo?>(null)
    val contactInfoSelection = _contactInfoSelection.asStateFlow()

    // 联系人组信息选择状态流
    private val _contactGroupInfoSelection = MutableStateFlow<ContactGroupInfo?>(null)
    val contactGroupInfoSelection = _contactGroupInfoSelection.asStateFlow()

    // 注意：更新查找字段的函数本质上存在竞争条件。当调度新的查找时，我们不会尝试中止之前的查找，
    // 因为它们基本上总是比用户反应完成得更快。

    /**
     * 根据查找键查找联系人
     * @param lookupKey 联系人的查找键
     */
    fun lookUpContact(lookupKey: String) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                val contact = try {
                    getContactByLookupKey(getApplication(), lookupKey)
                } catch (e: SecurityException) {
                    Log.w(TAG, "查找联系人时权限被拒绝", e)
                    null
                } catch (e: Exception) {
                    Log.w(TAG, "查找联系人失败", e)
                    null
                }

                _contactInfoLookup.update { contact }
            }
        }
    }

    /**
     * 根据ID查找联系人组
     * @param rowId 联系人组的行ID
     * @param sourceId 联系人组的源ID
     */
    fun lookUpContactGroup(rowId: Long, sourceId: String?) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                val groupLookup = if (sourceId != null) {
                    GroupLookup.SourceId(sourceId)
                } else {
                    GroupLookup.RowId(rowId)
                }

                val group = try {
                    getContactGroupById(getApplication(), groupLookup)
                } catch (e: SecurityException) {
                    Log.w(TAG, "查找联系人组时权限被拒绝", e)
                    null
                } catch (e: Exception) {
                    Log.w(TAG, "查找联系人组失败", e)
                    null
                }

                _contactGroupInfoLookup.update { group }
            }
        }
    }

    /**
     * 根据URI选择联系人
     * @param uri 联系人的URI
     */
    fun selectContact(uri: Uri) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                val contact = try {
                    withContactsByUri(getApplication(), uri) { it.firstOrNull() }
                } catch (e: Exception) {
                    Log.w(TAG, "查询联系人失败 $uri", e)
                    null
                }
                if (contact == null) {
                    Log.w(TAG, "未找到联系人 $uri")
                }

                _contactInfoSelection.update { contact }
            }
        }
    }

    /**
     * 选择联系人组
     * @param group 联系人组信息
     */
    fun selectContactGroup(group: ContactGroupInfo) {
        _contactGroupInfoSelection.update { group }
    }

    /**
     * 使用选中的联系人
     * 将选中的联系人设置为当前查找的联系人
     */
    fun useSelectedContact() {
        val contact = _contactInfoSelection.getAndUpdate { null }
        _contactInfoLookup.update { contact }
    }

    /**
     * 使用选中的联系人组
     * 将选中的联系人组设置为当前查找的联系人组
     */
    fun useSelectedContactGroup() {
        val group = _contactGroupInfoSelection.getAndUpdate { null }
        _contactGroupInfoLookup.update { group }
    }

    // 伴生对象
    companion object {
        // 日志标签
        private val TAG = RecordRuleEditorViewModel::class.java.simpleName
    }
}